"""
核心逻辑
"""
import datetime

from db.dbhandler import save, read
from lib.common import *

from db.models import User

current_user = []


def register():
    """注册"""
    username = loop_input('请输入要注册的用户名:', '用户已存在,请重新输入', lambda x: not is_user_exist(x))
    password = input('请输入用户密码:').strip()
    encrypted_password, pass_salt = encryption_password(password)

    user = User(username, encrypted_password, pass_salt)
    save(user)
    print(f'用户{username}注册成功!')


def login():
    """登录"""
    if not os.listdir(USER_DIR):
        print('当前系统无用户,请先注册!')
        return False
    username = input('请输入要登录的用户名:').strip()
    if not is_user_exist(username):
        print('用户不存在!请先注册!')
        return False
    # 获取用户
    user = read(username)

    # 用户锁定
    if user.is_locked:
        print(f'用户{username}被锁定,请联系管理员!')
        return False

    # 三次输入机会
    for i in range(4):
        password = input('请输入用户密码:').strip()
        encrypted_password, pass_salt = encryption_password(password, user.pass_salt)
        if i == 2:
            user.is_locked = True
            save(user)
            print('密码错误超过3次,用户已锁定!')
            return False
        if not encrypted_password == user.password:
            print(f'密码错误!你还有{2 - i}次机会!')
            continue
        break
    if current_user:
        current_user[0] = user
    else:
        current_user.append(user)
    print(f'用户{username}登录成功!')
    return True


@login_auth(current_user)
def check_balance():
    """查看余额"""
    user = current_user[0]
    pretty_print(['用户名', '当前余额'], [[user.username, user.balance]])


@login_auth(current_user)
def charge():
    """充值"""
    user = current_user[0]
    amount = float(loop_input('请输入要充值的金额:', '只能输入大于0的数字!请重新输入!', lambda x: x.isdigit()))
    # 余额增加 记录流水
    user.balance += amount
    user.flow.append([f'{datetime.datetime.now()}', '充值', amount])
    save(user)
    print(f"{datetime.datetime.now()} {user.username}充值成功{amount}元!")
    check_balance()


@login_auth(current_user)
def withdraw():
    """提现"""
    user = current_user[0]
    amount = float(
        loop_input('请输入要提现的金额(5%手续费):',
                   '只能输入大于0的数字!请重新输入!',
                   lambda x: x.isdigit()))
    total = amount + amount * 0.05
    if total > user.balance:
        print('当前余额不足 提现金额+手续费 ,请先充值!')
        return
    # 余额扣除 记录流水
    user.balance -= total
    user.flow.append([f'{datetime.datetime.now()}', '提现', amount])
    user.flow.append([f'{datetime.datetime.now()}', '提现手续费', amount * 0.05])
    save(user)
    print(f"{datetime.datetime.now()} {user.username}提现成功{amount}元 手续费{amount * 0.05}元!")
    check_balance()


@login_auth(current_user)
def transfer():
    """转账"""
    user = current_user[0]
    if len(os.listdir(USER_DIR)) < 2:
        print('当前系统仅有当前一个用户,无法使用转账功能!')
        return
    target_username = loop_input(
        '请输入要转账目标的用户名:',
        '用户不存在或转账目标不能是自己,请重新输入',
        lambda x, username: is_user_exist(x) and not x == username, user.username
    )
    amount = float(loop_input('请输入要转账的金额:', '只能输入大于0的数字!请重新输入!', lambda x: x.isdigit()))

    if amount > user.balance:
        print('当前余额不足,请先充值!')
        return
    # 修改当前用户 和 转账目标用户 余额 保存流水
    user.balance -= amount
    user.flow.append([f'{datetime.datetime.now()}', '转出', amount])
    target_user = read(target_username)
    target_user.balance += amount
    target_user.flow.append([f'{datetime.datetime.now()}', '转入', amount])
    print(f"{datetime.datetime.now()}' 用户{user.username}转账给用户{target_username}:{amount}元!")
    save(user)
    save(target_user)


@login_auth(current_user)
def check_flow():
    """查看流水"""
    user = current_user[0]
    if not user.flow:
        print('当前用户流水为空!')
    pretty_print(['时间', '流水类型', '金额'], user.flow)


@login_auth(current_user)
@admin_auth(current_user)
def change_balance():
    """修改余额"""
    # 打印全部用户和余额
    all_user_list = get_all_user()
    data_list = []
    for user in all_user_list:
        data_list.append([user.username, user.balance])
    pretty_print(['用户名', '余额'], data_list)
    # 输入
    username = loop_input(
        '请输入要修改余额的用户名:',
        '用户不存在,请重新输入',
        lambda x: is_user_exist(x)
    )
    amount = float(loop_input('请输入修改后的金额:', '只能输入大于0的数字!请重新输入!', lambda x: x.isdigit()))
    # 修改余额 保存流水
    user = read(username)
    user.balance = amount
    user.flow.append([f'{datetime.datetime.now()}', '修改余额', amount])
    save(user)
    print(f"{datetime.datetime.now()} {user.username}余额修改为{amount}元!")


@login_auth(current_user)
@admin_auth(current_user)
def lock_user():
    """锁定用户"""
    # 打印全部用户和锁定状态
    all_user_list = get_all_user()
    data_list = []
    for user in all_user_list:
        data_list.append([user.username, '锁定' if user.is_locked else '正常'])
    pretty_print(['用户名', '状态'], data_list)
    # 输入
    username = loop_input(
        '请输入要锁定/解锁的用户名:',
        '用户不存在,请重新输入',
        lambda x: is_user_exist(x)
    )
    user = read(username)
    # 锁定或解锁
    user.is_locked = not user.is_locked
    save(user)
    if user.is_locked:
        print(f'用户{username}已锁定!')
    else:
        print(f'用户{username}已解锁!')


# 功能字典
src_dict = {
    '1': register,
    '2': login,
    '3': check_balance,
    '4': charge,
    '5': withdraw,
    '6': transfer,
    '7': check_flow,
    '8': change_balance,
    '9': lock_user,
}


def run():
    while True:
        print('欢迎使用ATM系统'.center(16, '*'))
        title_list = ['功能列表']
        data_list = [['用户注册'], ['用户登录'], ['查看余额'],
                     ['充值功能'], ['提现功能'], ['转账功能'],
                     ['查看流水'], ['修改余额'], ['锁定用户']]
        # 菜单美化打印
        pretty_print(title_list, data_list, auto_index=True)

        if current_user:
            print(f'当前用户: {current_user[0].username} 余额: {current_user[0].balance} 元')
        else:
            print('当前用户: 未登录'.center(16, '*'))

        print('--输入q退出系统,Q退出登录--')
        order = input('请输入功能编号:').strip()
        # 退出
        if order == 'q':
            print('退出系统!')
            exit(0)
        # 退出登录
        if order == 'Q' and current_user:
            print(f"{current_user[0].username}退出登录!")
            input('按回车继续...')
            current_user.clear()
            continue
        # 未登录时 退出登录
        if order == 'Q' and not current_user:
            print('未登录,请先登录用户!')
            input('按回车继续...')
            continue
        # 输入错误
        if not src_dict.get(order):
            print('输入错误,请重新输入')

        src_dict[order]()

        input('按回车继续...')
